/**
 * @purpose 嵌套集合树节点。
 * @author daizs
 * @created Mar 4, 2010
 */
package platform.common.bo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;

import platform.common.dao.IDomainProvider;
import platform.common.dao.IDomainProviderSet;
import platform.common.dao.impl.CriticalTechnicalDaoException;
import platform.common.dao.impl.DaoConfigException;
import platform.common.dao.impl.DaoException;
import platform.common.dao.impl.TechnicalDaoException;
import platform.common.exception.BusinessException;
import platform.common.exception.CriticalTechnicalException;
import platform.common.exception.InValidDataException;
import platform.common.exception.TechnicalException;

import com.google.gson.Gson;

public abstract class AbstractNestedSetTreeNode extends IdentifiableObj implements INestedSetTreeNode,Serializable {
	/**
	 * 节点名称
	 */
	private String name;
	/**
	 * 节点编码。通常是能够表示节点层次关系的编码，如:1,1.1,1.2,1.1.2等。
	 */
	private String code;
	/**
	 * 节点的左值
	 */
	private int leftValue;
	/**
	 * 节点的右值
	 */
	private int rightValue;
	/**
	 * 隔离标识。因为一张表要保存多颗不同的树。不同的树用隔离标识区隔。
	 */
	protected String isolatedFlag;
	/**
	 * 节点的距离根节点的层次。
	 */
	private int treeLevel;

	private String memo;//说明
	
	private String strutSign;

	public String getStrutSign() {
		return strutSign;
	}

	public void setStrutSign(String strutSign) {
		this.strutSign = strutSign;
	}

	public String getMemo() {
		return memo;
	}

	public void setMemo(String memo) {
		this.memo = memo;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getLeftValue() {
		return leftValue;
	}

	public void setLeftValue(int leftValue) {
		this.leftValue = leftValue;
	}

	public int getRightValue() {
		return rightValue;
	}

	public void setRightValue(int rightValue) {
		this.rightValue = rightValue;
	}


	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getIsolatedFlag() {
		return isolatedFlag;
	}

	public void setIsolatedFlag(String isolatedFlag) {
		this.isolatedFlag = isolatedFlag;
	}



	public int getTreeLevel() {
		return treeLevel;
	}

	public void setTreeLevel(int treeLevel) {
		this.treeLevel = treeLevel;
	}

	/**
	 * 更新一个嵌套集合树节点，不改变节点在树的位置，只更新内容，即不改变节点的左右值
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public void store(IDomainProviderSet domainProviderSet) throws BusinessException {
		try {
			domainProviderSet.getDao().updateTreeNode(this);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}

	/**
	 * 插入一个嵌套集合树节点
	 *
	 * @param parentId 父节点ID
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public Serializable insertIntoDB(Serializable parentId,IDomainProviderSet domainProviderSet) throws BusinessException {
		try {
			//插入前的验证
			if(parentId==null){
				//判断层次为0的节点是否存在重名
				if(!isSameNameByTopNode(domainProviderSet)){
					return domainProviderSet.getDao().insertTreeNode(this, parentId);
				}
			}else{
				//校验同一个parentId下是否有重名的子节点
				if(!this.exsitSameNameNotSelfInParent(domainProviderSet,parentId)){
					return domainProviderSet.getDao().insertTreeNode(this, parentId);
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return null;
	}
	/**
	 * 
	 * <br/>方法描述:判断顶级节点是否存在重名
	 * @return true：存在;false:不存在同名
	 * @throws BusinessException
	 */
	public boolean isSameNameByTopNode(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			List list = null;
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			Map map = new HashMap();
			map.put("name", this.getName());
			if(this.getId()!=null && !this.getId().equals("")){
				map.put("id", this.getId());
				list = domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider, "sameNameByTopNodeOutId", map);
			}else{
				list = domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider, "sameNameByTopNode", map);
			}
			if(list.size()>0){
				Gson gson = new Gson();
				Map checkMap=new HashMap();
				checkMap.put("Name", "有重复的名称存在,请修改!");
				throw new InValidDataException(gson.toJson(checkMap));
			}
		}  catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return false;
		
	}

	/**
	 * 获得本节点的孩子节点（即直接下级）
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public List getChildren(IDomainProviderSet domainProviderSet) throws BusinessException {
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		Object[] qryParams=new Object[]{new Integer(this.getLeftValue())};
		List returnList=new ArrayList();
		try {
			returnList=domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"findChildren", qryParams);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return returnList;
	}


	/**
	 * 获得本节点的父节点
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public AbstractNestedSetTreeNode getParent(IDomainProviderSet domainProviderSet) throws BusinessException {
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		Map map = new HashMap();
		//设置查询参数
		map.put("treeLevel", this.treeLevel-1);
		map.put("leftValue", this.getLeftValue());
		map.put("rightValue", this.getRightValue());
		map.put("isolatedFlag", this.getIsolatedFlag());
		try {
			//查询父节点
			List returnList=domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"findParent", map);
			if(returnList.size()>0){
				//获取父节点对象
				return (AbstractNestedSetTreeNode)returnList.get(0);
			}else{
				//未找到父节点
				return null;
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}

	/**
	 * 获得本节点的后代节点（即子孙节点）
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public List getDescendants(IDomainProviderSet domainProviderSet)
			throws BusinessException {
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		List returnList = new ArrayList();
		Map map = new HashMap();
//		map.put("treeLevel", this.treeLevel-1);
		map.put("leftValue", this.getLeftValue());
		map.put("rightValue", this.getRightValue());
		map.put("isolatedFlag", this.getIsolatedFlag());
		try {
			returnList=domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"findDescendants", map);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return returnList;
	}
	
	/**
	 * 获得本节点的后代节点（即子孙节点）
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public List getThisAndDescendants(IDomainProviderSet domainProviderSet)
			throws BusinessException {
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		List returnList = new ArrayList();
		Map map = new HashMap();
//		map.put("treeLevel", this.treeLevel-1);
		map.put("leftValue", this.getLeftValue());
		map.put("rightValue", this.getRightValue());
		map.put("isolatedFlag", this.getIsolatedFlag());
		try {
			returnList=domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"findThisAndDescendants", map);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return returnList;
	}
	/**
	 * <br/>方法描述:得到所有叶子子孙节点
	 * @param domainProviderSet 业务领域提供者集合
	 * @return 叶子子孙节点集合
	 */
	public List getLeafDescendants(IDomainProviderSet domainProviderSet)throws BusinessException{
		//TODO
		return null;
	}

	/**
	 * 获得领域对象名称。具体嵌套集合树节点对象需要实现该方法
	 *
	 * @param domainProviderSet 领域对象提供者集合
	 * @throws BusinessException
	 */
	public abstract String getMyDomainObjName();

	/**
	 * <br/>方法描述:判断同父亲下非自己ID是否存在此名称
	 * @param domainProviderSet 业务领域提供者集合
	 * @return true:存在同名;false:不存在同名
	 */
	public boolean exsitSameNameNotSelfInParent(IDomainProviderSet domainProviderSet,Serializable parentId)throws BusinessException{
		return false;
	}
	
	/**
	 * 
	 * <br/>方法描述:根据id删除节点及其子孙节点
	 * @param domainProviderSet
	 * @throws BusinessException
	 */
	public void deleteById(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			//删除前的检查操作,返回true执行删除操作
			if(this.checkBeforeDelete(domainProviderSet)){
				//执行删除操作
				domainProviderSet.getDao().delTreeNodeById(this.getClass(), this.getId());
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		
	}
	
	/**
	 * 
	 * <br/>方法描述:删除前的检查操作
	 * @param domainProviderSet
	 * @return true:可删除;false;不可删除
	 * @throws BusinessException
	 */
	public boolean checkBeforeDelete(IDomainProviderSet domainProviderSet)throws BusinessException{
		return true;
	}

	/**
	 * 
	 * <br/>方法描述:获取所有父节点
	 * @param domainProviderSet
	 * @return
	 * @throws BusinessException
	 */
	public List getAncestors(IDomainProviderSet domainProviderSet)throws BusinessException{
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		List returnList = new ArrayList();
		try {
			Map map = new HashMap();
			map.put("leftValue", this.getLeftValue());
			map.put("rightValue", this.getRightValue());
			map.put("isolatedFlag", this.getIsolatedFlag());
			returnList = domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"findAncestors", map);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return returnList;
	}
	
	/**
	 * <br/>方法描述:插入一个新节点(插入兄弟节点)
	 * @param brotherId 兄弟节点
	 * @param domainProviderSet 业务领域提供者集合
	 */
	public void insertIntoBrotherDB(Serializable brotherId,
			IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			//插入前的验,通过兄弟节点证校验同级是否存在重名
			if(!this.exsitSameNameNotSelfByBother(domainProviderSet,brotherId)){
				domainProviderSet.getDao().insertTreeNodeBrother(this, brotherId);
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	
	
	/**
	 * <br/>方法描述:根据兄度判断同级是否存重名
	 * @param domainProviderSet 业务领域提供者集合
	 * @return true:存在同名;false:不存在同名
	 */
	public boolean exsitSameNameNotSelfByBother(IDomainProviderSet domainProviderSet,Serializable brotherId)throws BusinessException{
		return false;
	}
	
	/**
	 * 
	 * <br/>方法描述:上移某个节点(同级兄弟之间)
	 * @param domainProviderSet 业务领域提供者集合
	 * @return
	 */
	public void moveUp(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			//判断是否存在哥哥节点
			AbstractNestedSetTreeNode abstractNestedSetTreeNode = this.getParent(domainProviderSet);
			//本节点的左值减去父节点的左值==1,此节点为第一个子节点
			if(abstractNestedSetTreeNode==null || this.getLeftValue()-abstractNestedSetTreeNode.getLeftValue()==1){
				//此节点已经处于最前面,不能进行上移操作
				throw new BusinessException("此节点已经处于最前面,不能进行上移操作!");
			}else{
				//上移操作
				domainProviderSet.getDao().moveUp(this);
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		
		
		
	}
	/**
	 * 
	 * <br/>方法描述:下移某个节点(同级兄弟之间)
	 * @param domainProviderSet 业务领域提供者集合
	 * @return
	 */
	public void moveDown(IDomainProviderSet domainProviderSet) throws BusinessException{
		try {
			//判断是否存在弟弟节点
			AbstractNestedSetTreeNode abstractNestedSetTreeNode = this.getParent(domainProviderSet);
			//父节点的右值减去本节点的右值==1,此节点为最后一个子节点
			if(abstractNestedSetTreeNode==null || abstractNestedSetTreeNode.getRightValue()-this.getRightValue()==1){
				//此节点已经处于最后面,不能进行下移操作
				throw new BusinessException("此节点已经处于最后面,不能进行下移操作!");
			}else{
				//下移操作
				domainProviderSet.getDao().moveDown(this);
			}
		}catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		
	}
	/**
	 * 
	 * <br/>方法描述:根据id获取对象
	 * @param domainProviderSet 业务领域提供者集合
	 * @return
	 * @throws BusinessException
	 */
	public AbstractNestedSetTreeNode getTreeNodeById(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			return (AbstractNestedSetTreeNode)domainProviderSet.getDao().findByIdAndDomain(domainProvider, this.getId());
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	/**
	 * 
	 * <br/>方法描述:根据所展开的id获取需要展示数据的集合
	 * @param domainProviderSet
	 * @return
	 * @throws BusinessException
	 */
	public List loadFullTree(IDomainProviderSet domainProviderSet,String ids) throws BusinessException{
		List list = new ArrayList();
		try {
			//获取所有某平台下的所有结构
			list = this.loadFullTree(domainProviderSet);
			//按id集合过滤需要展示的节点
			list = this.filtrateByIds(list, ids);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return list;
	}
	/**
	 * 
	 * <br/>方法描述:加载某棵树的所有节点
	 * @param domainProviderSet
	 * @return
	 * @throws BusinessException
	 */
	public List loadFullTree(IDomainProviderSet domainProviderSet)throws BusinessException{
		List list = new ArrayList();
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			//按id获取对象
			AbstractNestedSetTreeNode treeNode = this.getTreeNodeById(domainProviderSet);
			String isolatedFlagTemp = treeNode.getIsolatedFlag();
			Object[] qryParams = new Object[] { isolatedFlagTemp };
			//获取所有某平台下的所有结构
			list = domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"loadFullTree", qryParams);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return list;
	}
	/**
	 * 
	 * <br/>方法描述:根据所展开的id，查询出对应的对象(除需要移动和复制节点及其子孙节点)，放到集合中
	 * @param domainProviderSet
	 * @param ids
	 * @return
	 * @throws BusinessException
	 */
	public List loadTreeOutById(IDomainProviderSet domainProviderSet,String ids)throws BusinessException{
		List list = new ArrayList();
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			//按id获取对象
			AbstractNestedSetTreeNode treeNode = this.getTreeNodeById(domainProviderSet);
			//获取所有某平台下的所有结构
			list = this.loadFullTree(domainProviderSet);
			//按id集合过滤需要展示的节点,且不包括某个节点及其子孙节点
			list = this.filtrateByIdsOutById(list, ids, treeNode.getLeftValue(), treeNode.getRightValue());
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return list;
	}
	/**
	 * 
	 * <br/>方法描述:按id集合过滤数据集合
	 * @param list 数据集合
	 * @param ids id集合
	 * @return 符合数据的集合
	 * @throws BusinessException
	 */
	public List filtrateByIds(List list,String ids)throws BusinessException{
		//存放返回集合
		List<AbstractNestedSetTreeNode> listReturn = new ArrayList<AbstractNestedSetTreeNode>();
		try {
			//用于存放跳过记录的行数
			int strutCount = 0;
			for (int i = 0; i < list.size(); i++) {
				AbstractNestedSetTreeNode abstractNestedSetTreeNode = (AbstractNestedSetTreeNode) list.get(i);
				String id = abstractNestedSetTreeNode.getId().toString();
				//判断此节点是否为展开节点
				if (ids.equals(id) || ids.startsWith(id + ",") || ids.indexOf("," + id + ",") > -1|| ids.endsWith("," + id)) {
					listReturn.add(abstractNestedSetTreeNode);
				} else {
					//这是展开的节点带出来显示的节点,这里的节点的下级都不需要现在,通过左右值计算跳过的记录条数
					listReturn.add(abstractNestedSetTreeNode);
					//通过左右值计算跳过的记录条数
					strutCount = (abstractNestedSetTreeNode.getRightValue() - abstractNestedSetTreeNode.getLeftValue() - 1) / 2;
					//设置下次循环进入的记录
					i = i + strutCount;
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return listReturn;
	}
	
	/**
	 * 
	 * <br/>方法描述:按id集合过滤数据集合
	 * @param list 数据集合
	 * @param ids id集合
	 * @return 符合数据的集合
	 * @throws BusinessException
	 */
	public List filtrateByIdsOutById(List list,String ids,int leftValue,int rightValue)throws BusinessException{
		//存放返回集合
		List<AbstractNestedSetTreeNode> listReturn = new ArrayList<AbstractNestedSetTreeNode>();
		try {
			//用于存放跳过记录的行数
			int strutCount = 0;
			for (int i = 0; i < list.size(); i++) {
				AbstractNestedSetTreeNode abstractNestedSetTreeNode = (AbstractNestedSetTreeNode) list.get(i);
				if(abstractNestedSetTreeNode.getLeftValue()>=leftValue && abstractNestedSetTreeNode.getRightValue()<=rightValue){
					continue;
				}
				String id = abstractNestedSetTreeNode.getId().toString();
				//判断此节点是否为展开节点
				if (ids.equals(id) || ids.startsWith(id + ",") || ids.indexOf("," + id + ",") > -1|| ids.endsWith("," + id)) {
					listReturn.add(abstractNestedSetTreeNode);
				} else {
					//这是展开的节点带出来显示的节点,这里的节点的下级都不需要现在,通过左右值计算跳过的记录条数
					listReturn.add(abstractNestedSetTreeNode);
					//通过左右值计算跳过的记录条数
					strutCount = (abstractNestedSetTreeNode.getRightValue() - abstractNestedSetTreeNode.getLeftValue() - 1) / 2;
					//设置下次循环进入的记录
					i = i + strutCount;
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return listReturn;
	}
	
	/**
	 *
	 * <br/>方法描述: 判断两个节点是否为同一个父亲
	 * @param domainProviderSet
	 * @param origTreeNodeId
	 * @param destTreeNodeId
	 * @return
	 * @throws BusinessException
	 */
	public boolean isSameParent(IDomainProviderSet domainProviderSet,Serializable origTreeNodeId,Serializable destTreeNodeId)throws BusinessException{
		try {
			//获取源节点父节点
			AbstractNestedSetTreeNode origTreeNodeParent = this.getParent(domainProviderSet);
			//判断两个父节点是否相同
			if(origTreeNodeParent!=null  && origTreeNodeParent.getId().equals(destTreeNodeId)){
				//抛出异常进行移动、复制操作
				throw new BusinessException("选择的目标节点位置不能是本节点的父节点!");
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return false;
	}
	/**
	 * 
	 * <br/>方法描述:根据隔离标识删除一棵树
	 * @param domainProviderSet
	 * @throws BusinessException
	 */
	public void deleteByIsolatedFlag(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			Map map = new HashMap();
			map.put("isolatedFlag", this.getIsolatedFlag());
			domainProviderSet.getDao().exeByHqlNameAndDomian(domainProvider, "deleteByIsolatedFlag", map);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	/**
	 * 
	 * <br/>方法描述:
	 * @param domainProviderSet 业务领域提供者集合
	 * @param changeValue 左右值改变的值
	 * @throws BusinessException
	 */
	public void updateLeftRightValue(IDomainProviderSet domainProviderSet,int changeValue)throws BusinessException{
		try {
			//修改左值
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			Map map = new HashMap();
			map.put("isolatedFlag", this.getIsolatedFlag());
			map.put("changeValue", changeValue);
			map.put("leftValue", this.getRightValue());
			domainProviderSet.getDao().exeByHqlNameAndDomian(domainProvider, "upateLeftValue", map);
			//修改右值
			map = new HashMap();
			map.put("isolatedFlag", this.getIsolatedFlag());
			map.put("changeValue", changeValue);
			map.put("rightValue", this.getRightValue());
			domainProviderSet.getDao().exeByHqlNameAndDomian(domainProvider, "upateRightValue", map);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	
	/**
	 * 
	 * <br/>方法描述:插入一个嵌套集合树节点,不需要构造左右值
	 * domainProviderSet 业务领域提供者集合
	 * @throws DaoException
	 */
	public void insertTreeNodeNotSetLR(IDomainProviderSet domainProviderSet)throws BusinessException{
		try {
			domainProviderSet.getDao().insertTreeNodeNotSetLR(this);
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		
	}
	
	
	/**
	 * 
	 * <br/>方法描述:新建平台拷贝参考平台的结构,并修改id和隔离表示
	 * @param domainProviderSet
	 * @param copyTreeId参考平台id
	 * @return int 返回新建平台的右值
	 * @throws BusinessException
	 */
	public int copyByTree(IDomainProviderSet domainProviderSet,String newIsolatedFlag)throws BusinessException{
		//返回顶级节点的右值
		int rightValue = 0;
		IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
		try {
			AbstractNestedSetTreeNode newTreeNode = null;
			//获取参考平台的所有结构
			List list = this.loadFullTree(domainProviderSet);
			for(int i=0;i<list.size();i++){
				AbstractNestedSetTreeNode treeNode = (AbstractNestedSetTreeNode)list.get(i);
				newTreeNode = (AbstractNestedSetTreeNode)domainProvider.newEmptyObj();
				if(treeNode.getTreeLevel()==0){
					rightValue = treeNode.getRightValue();
				}else{
					//拷贝属性
					BeanUtils.copyProperties(list.get(i), newTreeNode);
					newTreeNode.generatorUUID();
					domainProviderSet.getDao().insertTreeNodeNotSetLR(newTreeNode);
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
		return rightValue ;
	}
	
	/**
	 * 
	 * <br/>方法描述:把某节点及其子孙节点复制到另一个节点下
	 * @param origTreeNodeId 被复制节点id
	 * @param destTreeNodeId 复制目的节点id
	 * @throws DaoException
	 */
	public void copyTreeNode(IDomainProviderSet domainProviderSet,Serializable origTreeNodeId,Serializable destTreeNodeId)throws BusinessException{
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			
			//判断两个节点是否为同一个父亲(不能复制成自己的兄弟节点)
			if(!this.isSameParent(domainProviderSet, origTreeNodeId, destTreeNodeId)){
				//重名判断(destTreeNodeId子节点)
				//插入前的验证
				if(!this.exsitSameNameNotSelfInParent(domainProviderSet,destTreeNodeId)){
					//拷贝节点
					//获取需要复制的节点对象
					AbstractNestedSetTreeNode origTreeNode = (AbstractNestedSetTreeNode) domainProviderSet
							.getDao().findByIdAndDomain(domainProvider,origTreeNodeId);
					//获取复制目的节点对象
					AbstractNestedSetTreeNode destTreeNode = (AbstractNestedSetTreeNode)domainProviderSet
							.getDao().findByIdAndDomain(domainProvider, destTreeNodeId);
					this.copyTreeNode(domainProviderSet, origTreeNode, destTreeNode);
					domainProviderSet.getDao().copyTreeNode(domainProvider, domainProvider.getDomainClass(), origTreeNode, destTreeNode);
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	
	/**
	 * 
	 * <br/>方法描述:复制节点,且重新设置左右值和层次、数据标识
	 * @param domainProviderSet
	 * @param origTreeNode
	 * @param destTreeNode
	 * @throws BusinessException
	 */
	public void copyTreeNode(IDomainProviderSet domainProviderSet,
			AbstractNestedSetTreeNode origTreeNode,AbstractNestedSetTreeNode destTreeNode)throws BusinessException{
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			//复制节点新左右值和原来左右值的差量
			int changeValue = origTreeNode.getLeftValue()-destTreeNode.getRightValue();
			//复制节点新层次和原来左右值的差量
			int changTreeLevel = origTreeNode.getTreeLevel()-destTreeNode.getTreeLevel()-1;
			//获取需要复制的节点
			Map map = new HashMap();
			map.put("leftValue", origTreeNode.getLeftValue());
			map.put("rightValue", origTreeNode.getRightValue());
			map.put("isolatedFlag", origTreeNode.getIsolatedFlag());
			List listForCopy=domainProviderSet.getDao().findByHqlNameAndDomian(domainProvider,"copyNodes", map);
			AbstractNestedSetTreeNode newTreeNode = null;
			//复制节点且更新节点的左右值和层次,并在这些数据上加上标识,以区分相同左右值节点
			for(int i=0;i<listForCopy.size();i++){
				AbstractNestedSetTreeNode treeNode = (AbstractNestedSetTreeNode) listForCopy.get(i);
				newTreeNode = (AbstractNestedSetTreeNode)domainProvider.newEmptyObj();
				BeanUtils.copyProperties(listForCopy.get(i), newTreeNode);
				newTreeNode.setLeftValue(newTreeNode.getLeftValue()-changeValue);
				newTreeNode.setRightValue(newTreeNode.getRightValue()-changeValue);
				newTreeNode.setTreeLevel(newTreeNode.getTreeLevel()-changTreeLevel);
				newTreeNode.setStrutSign("1");
				newTreeNode.generatorUUID();
				domainProviderSet.getDao().insertTreeNodeNotSetLR(newTreeNode);
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	
	/**
	 * 
	 * <br/>方法描述:把某节点及其子孙节点移动到另一个节点下
	 * @param origTreeNodeId 被移动节点id
	 * @param destTreeNodeId 移动目的节点id
	 * @throws DaoException
	 */
	public void moveTreeNode(IDomainProviderSet domainProviderSet,Serializable origTreeNodeId,Serializable destTreeNodeId)throws BusinessException{
		try {
			IDomainProvider domainProvider=domainProviderSet.getDomainProviderByName(getMyDomainObjName());
			//判断两个节点是否为同一个父亲(不能移动成自己的兄弟节点)
			if(!this.isSameParent(domainProviderSet, origTreeNodeId, destTreeNodeId)){
				//重名判断(destTreeNodeId子节点)
				//插入前的验证
				if(!this.exsitSameNameNotSelfInParent(domainProviderSet,destTreeNodeId)){
					//移动节点
					//获取需要复制的节点对象
					AbstractNestedSetTreeNode origTreeNode = (AbstractNestedSetTreeNode) domainProviderSet
							.getDao().findByIdAndDomain(domainProvider,origTreeNodeId);
					//获取复制目的节点对象
					AbstractNestedSetTreeNode destTreeNode = (AbstractNestedSetTreeNode)domainProviderSet
							.getDao().findByIdAndDomain(domainProvider, destTreeNodeId);
					this.copyTreeNode(domainProviderSet, origTreeNode, destTreeNode);
					domainProviderSet.getDao().moveTreeNode(domainProvider, domainProvider.getDomainClass(), origTreeNode, destTreeNode);
				}
			}
		} catch (Exception e) {
			throw this.handleBusinessClientException(e);
		}
	}
	
	

	public BusinessException handleBusinessClientException(String errMsg, Exception e) {
		if(e instanceof CriticalTechnicalDaoException) {
			return new CriticalTechnicalException(e);
		} else if(e instanceof TechnicalDaoException) {
			return new TechnicalException(e);
		} else if(e instanceof DaoConfigException) {
			return new CriticalTechnicalException(e);
		} else if(e instanceof DaoException) {
			return new TechnicalException(e);
		} else if(e instanceof InValidDataException) {
			return (InValidDataException) e;
		}  else if(e instanceof BusinessException) {
			return (BusinessException) e;
		} else {
			return new BusinessException(errMsg, e);
		}
	}

	public BusinessException handleBusinessClientException(Exception e) {
		return this.handleBusinessClientException("", e);
	}
	
}
